package com.gmrz.uaf.servlet.v1.handler;

import com.gmrz.service.challengestore.ChallengeStoreService;
import com.gmrz.uaf.common.Constants;
import com.gmrz.uaf.common.GuiceUtil;
import com.gmrz.uaf.protocol.v1.json.UAFSchemaBuilder;
import com.gmrz.uaf.protocol.v1.processor.UAFDeregisterProcessor;
import com.gmrz.uaf.protocol.v1.schema.DeregisterAuthenticator;
import com.gmrz.uaf.protocol.v1.schema.DeregisterationRequest;
import com.gmrz.uaf.server.ServerContext;
import com.gmrz.uaf.servlet.v1.request.DeregContext;
import com.gmrz.uaf.servlet.v1.request.ReceiveReqPayload;
import com.gmrz.uaf.servlet.v1.response.FidoRespPayload;
import com.gmrz.uaf.servlet.v1.validation.PayloadValidationException;
import com.gmrz.uaf.servlet.v1.validation.RestValidator;
import com.gmrz.util.Convert;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by yangairong on 16/12/29.
 */
public class UAFDeregAllRequestHandler extends UAFBaseHandler {
    private static final Logger LOG = LogManager.getLogger(UAFDeregAllRequestHandler.class);

    /**
     * {
     * "context":{
     * "transNo":"32characters",
     * "userName":"user1",
     * "appID","001"
     * }
     * }
     *
     * @param request
     * @return {
     * "statusCode":1200,
     * "description":"OK",
     * "uafRequest":"[
     * "[{\"header\":{....},\"policy\":{.....}}]"
     * ]"
     * }
     */

    public String deleteAll(String request) {
        LOG.info("[/reg/deleteall][begin]");
        ServerContext.getServerContext().getFidoLog().setRequest(request);
        Gson gson = UAFSchemaBuilder.getGson();
        FidoRespPayload<String> respPayload = new FidoRespPayload<String>();
        Type reqType = new TypeToken<ReceiveReqPayload<DeregContext>>() {
        }.getType();

        String response = null;
        try {
            // 将请求串转为对象
            ReceiveReqPayload<DeregContext<List<String>>> reqPayload = gson.fromJson(request, reqType);
            // 日志记录
            logRequest(request, reqPayload.getContext().getTransNo(), reqPayload.getContext().getUserName(),
                    reqPayload.getContext().getAppID(), null, null, Constants.Method.DEREG_ALL);
            // 校验请求参数
            validateAll(reqPayload);
            ServerContext.getServerContext().setBase64(reqPayload.getContext().isBase64());
            UAFDeregisterProcessor deregisterProcessor = GuiceUtil.getProcessorInjector()
                    .getInstance(UAFDeregisterProcessor.class);

            DeregContext<List<String>> context = reqPayload.getContext();

            if(null == context.getTransType() || context.getTransType().size() <= 0 ) {
                List<String> transTypeList = new ArrayList<String>();
                transTypeList.add("00");
                transTypeList.add("01");
                transTypeList.add("02");
                context.setTransType(transTypeList);
            }
            // hash 用户名
            String userName = generateHashedUserName(context.getUserName(), context.getRf1(), context.getRf2());
            // 注销多个认证方式
            DeregisterationRequest requests = deregisterProcessor.deleteAll(userName, context.getAppID(),
                    context.getDeviceID(), context.getAuthType(), context.getTransType(), context.getFrom(),context.getCancelReason());
            // 返回一个不可变的list集合
            List deregisterationRequests = Collections.singletonList(requests);
            // 构造响应串
            response = buildReceiveResponse(gson, respPayload, deregisterationRequests);

            for (String authType : context.getAuthType()) {
                for (String transType : context.getTransType()) {
                    try {
                        // 将redis缓存中存储的认证数据全部删除
                        delCache(context.getAppID(), context.getDeviceID(), userName, authType, transType);
                    }catch (Exception e){

                    }
                }
            }
            ChallengeStoreService challengeStoreService = GuiceUtil.getProcessorInjector().getInstance(ChallengeStoreService.class);

            if(null != requests && null != requests.getDeregisterAuthenticators()) {
                for (String authType : context.getAuthType()) {
                    for (String transType : context.getTransType()) {
                        for(DeregisterAuthenticator deregisterAuthenticator : requests.getDeregisterAuthenticators()) {
                            String authErrorCountKey = Constants.AUTH_ERROR_COUNT + Convert.toBase64(deregisterAuthenticator.getKeyID().getId())+"."+ authType + "." + transType + "." + userName;
                            // 将redis中相关数据删除
                            challengeStoreService.deleteRedisValue(authErrorCountKey);
                        }
                    }
                }
            }

        } catch (Exception ex) {
            LOG.error(ex);
            response = buildFidoRespFromException(respPayload, ex);
        }
        LOG.info("[/reg/deleteall][end]");
        return response;
    }

    private void validateAll(ReceiveReqPayload<DeregContext<List<String>>> reqPayload)
            throws PayloadValidationException {
        if ((reqPayload == null) || (reqPayload.getContext() == null)) {
            throw new PayloadValidationException("context", RestValidator.VALIDATION_ERROR.EMPTY);
        }
        DeregContext<List<String>> context = reqPayload.getContext();
        RestValidator.validate("transNo", context.getTransNo());
        RestValidator.validate("userName", context.getUserName());
        RestValidator.validate("rf1", context.getRf1());
        RestValidator.validate("rf2", context.getRf2());
        RestValidator.validate("appID", context.getAppID());
        if (!Strings.isNullOrEmpty(context.getDeviceID())) {
            RestValidator.validate("deviceID", context.getDeviceID());
        }
        List<String> authTypeList = context.getAuthType();
        if (null == authTypeList || authTypeList.isEmpty()) {
            throw new PayloadValidationException("authType", RestValidator.VALIDATION_ERROR.EMPTY);
        }
        for (String auth : authTypeList) {
            RestValidator.validate("authType", auth);
        }
        RestValidator.validate("from", context.getFrom());
    }


}
